package controllers

import (
	"errors"
	"gitee/yinlai/kms-backend/config"
	"gitee/yinlai/kms-backend/utils/logs"
	"github.com/dotbalo/kubeutils/kubeutils"
	"github.com/gin-gonic/gin"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
	"net/http"
)

// BasicInfo 定义全局的数据结构
type BasicInfo struct {
	ClusterId  string      `json:"clusterId" form:"clusterId"`
	Namespace  string      `json:"namespace" form:"namespace"`
	Name       string      `json:"name" form:"name"` // namespace
	Item       interface{} `json:"item" form:"item"` // 用于接受前端传递过来的参数 如namespace或者其他资源的字段
	DeleteList []string    `json:"deleteList"`
}

// Info 新增一个info对象，包含上面的BasicInfo
type Info struct {
	BasicInfo
	ReturnData    config.ReturnData
	LabelSelector string `json:"labelSelector" form:"labelSelector"` // 超看资源的标签
	FieldSelector string `json:"fieldSelector" form:"fieldSelector"` // listOption
	Force         bool   `json:"force" form:"force"`                 // 是否强制删除资源
}

func NewInfo(r *gin.Context, info *Info, returnDataMsg string) (kubeconfig string) {
	// 声明一个集群的配置
	//basicInfo := BasicInfo{}
	//basicInfo.Item = item
	// 获取当前请求的方法

	info.ReturnData.Status = 200
	info.ReturnData.Message = returnDataMsg
	requestMethod := r.Request.Method
	var err error

	if requestMethod == "GET" {
		err = r.ShouldBindQuery(&info)
	} else if requestMethod == "POST" {
		err = r.ShouldBindJSON(&info)
	} else {
		err = errors.New("不支持的请求类型")
	}
	logs.Debug(map[string]interface{}{"info": info}, "数据绑定结果")

	// 在config文件中定义的一个公共的数据返回对象
	if err != nil {
		msg := "请求出错：" + err.Error()
		info.ReturnData.Status = 400
		info.ReturnData.Message = msg
		logs.Error(nil, msg)
		r.JSON(http.StatusOK, info.ReturnData)
		return
	}

	// 获取kubeconfig
	kubeconfig = config.ClusterKubeconfig[info.ClusterId]

	// 直接返回
	return kubeconfig
}

// Create 公共方法统一执行创建资源的方法
func (c *Info) Create(r *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
	err := kubeUtilsInterface.Create(c.Namespace)
	if err != nil {
		msg := "创建失败" + err.Error()
		c.ReturnData.Status = 400
		c.ReturnData.Message = msg
		logs.Error(nil, msg)
	}
	r.JSON(http.StatusOK, c.ReturnData)
}

// Update 公共方法统一执行更新资源的方法
func (c *Info) Update(r *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
	err := kubeUtilsInterface.Update(c.Namespace)
	if err != nil {
		msg := "更新失败" + err.Error()
		c.ReturnData.Status = 400
		c.ReturnData.Message = msg
		logs.Error(nil, msg)
	}
	r.JSON(http.StatusOK, c.ReturnData)
}

// List 公共方法统一执行查看资源列表的方法
func (c *Info) List(r *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
	items, err := kubeUtilsInterface.List(c.Namespace, c.LabelSelector, c.FieldSelector)
	if err != nil {
		msg := "查询失败" + err.Error()
		c.ReturnData.Status = 400
		c.ReturnData.Message = msg
		logs.Error(nil, msg)
	} else {
		c.ReturnData.Data = make(map[string]interface{})
		c.ReturnData.Data["items"] = items
	}
	r.JSON(http.StatusOK, c.ReturnData)
}

// Get 公共方法统一执行查看资源的方法
func (c *Info) Get(r *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
	item, err := kubeUtilsInterface.Get(c.Namespace, c.Name)
	if err != nil {
		msg := "查询失败" + err.Error()
		c.ReturnData.Status = 400
		c.ReturnData.Message = msg
		logs.Error(nil, msg)
	} else {
		c.ReturnData.Data = make(map[string]interface{})
		c.ReturnData.Data["items"] = item
	}
	r.JSON(http.StatusOK, c.ReturnData)
}

// Delete 公共方法统一执行删除资源的方法
func (c *Info) Delete(r *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
	var gracePeriodSeconds int64
	if c.Force {
		var s int64 = 0
		gracePeriodSeconds = s
	}
	err := kubeUtilsInterface.Delete(c.Namespace, c.Name, &gracePeriodSeconds)
	if err != nil {
		msg := "删除失败" + err.Error()
		c.ReturnData.Status = 400
		c.ReturnData.Message = msg
		logs.Error(nil, msg)
	}
	r.JSON(http.StatusOK, c.ReturnData)
}

// DeleteList 公共方法统一执行删除一个列表资源的方法
func (c *Info) DeleteList(r *gin.Context, kubeUtilsInterface kubeutils.KubeUtilser) {
	var gracePeriodSeconds int64
	if c.Force {
		var s int64 = 0
		gracePeriodSeconds = s
	}
	err := kubeUtilsInterface.DeleteList(c.Namespace, c.BasicInfo.DeleteList, &gracePeriodSeconds)
	if err != nil {
		msg := "删除多个资源失败" + err.Error()
		c.ReturnData.Status = 400
		c.ReturnData.Message = msg
		logs.Error(nil, msg)
	}
	r.JSON(http.StatusOK, c.ReturnData)
}

func BasicInit(r *gin.Context, item interface{}) (clientset *kubernetes.Clientset, basicInfo BasicInfo, err error) {
	// 声明一个集群的配置
	basicInfo = BasicInfo{}
	basicInfo.Item = item
	// 获取当前请求的方法
	requestMethod := r.Request.Method
	if requestMethod == "GET" {
		err = r.ShouldBindQuery(&basicInfo)
	} else if requestMethod == "POST" {
		err = r.ShouldBindJSON(&basicInfo)
	} else {
		err = errors.New("不支持的请求类型")
	}
	logs.Debug(map[string]interface{}{"basicInfo": basicInfo}, "数据绑定结果")

	// 在config文件中定义的一个公共的数据返回对象
	if err != nil {
		msg := "请求出错：" + err.Error()
		return nil, basicInfo, errors.New(msg)
	}

	// 如果前端传递过来的namespace为空 设置一下默认值
	if basicInfo.Namespace == "" {
		basicInfo.Namespace = "default"
	}

	// 获取kubeconfig
	kubeconfig := config.ClusterKubeconfig[basicInfo.ClusterId]

	restConfig, err := clientcmd.RESTConfigFromKubeConfig([]byte(kubeconfig))
	if err != nil {
		logs.Error(map[string]interface{}{"id": basicInfo.ClusterId, "msg": err.Error()}, "解析kubeconfig错误")
		msg := "解析kubeconfig错误：" + err.Error()
		return nil, basicInfo, errors.New(msg)
	}
	clientset, err = kubernetes.NewForConfig(restConfig)
	if err != nil {
		logs.Error(map[string]interface{}{"id": basicInfo.ClusterId, "msg": err.Error()}, "创建clientset失败")
		msg := "创建clientset失败：" + err.Error()

		return nil, basicInfo, errors.New(msg)
	}
	return clientset, basicInfo, nil
}

/*
  代码优化思考
	1. namespace pod deployment... 资源的操作,每一资源，都是create,delete,update,list,get  ---> 思考我们可以声明一个接口
	2. 声明一个接口 kubeUtils
    3. 接口的方法... create,delete,update,list,get
    4. 使用kubeUtils 接口实现资源创建
*/
